﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Threading;

namespace TuDarmstadt.Informatik.TK.TnT.Captinect.Serializer
{
    public class SerializableBufferedFileWriter
    {
        private Object locker;
        private Queue<BufferedSerializableItem> items;

        public SerializableBufferedFileWriter()
        {
            locker = new Object();
            items = new Queue<BufferedSerializableItem>();
        }

        ~SerializableBufferedFileWriter()
        {
            Stop();
        }

        public bool IsStarted { get; private set; }

        public bool IsStopping { get; private set; }

        public void Enqueue(ISerializable serializable, string file)
        {
            lock (locker)
            {
                BufferedSerializableItem item = new BufferedSerializableItem(serializable, file);
                items.Enqueue(item);
                Monitor.PulseAll(locker);
            }
        }

        public void Start()
        {
            ThreadStart job = new ThreadStart(ConsumeItems);
            Thread thread = new Thread(job);
            thread.Start();
        }

        public void Stop()
        {
            IsStopping = true;
            lock (locker)
            {
                Monitor.PulseAll(locker);
            }
        }

        private void ConsumeItems()
        {
            IsStarted = true;
            while (!IsStopping)
            {
                lock (locker)
                {
                    while (items.Count == 0 && !IsStopping)
                    {
                        Monitor.Wait(locker);
                    }
                    if (items.Count != 0)
                    {
                        BufferedSerializableItem item = items.Dequeue();
                        Stream stream = File.Open(item.Filename, FileMode.Append);
                        BinaryFormatter formatter = new BinaryFormatter();
                        formatter.Serialize(stream, item.Serializable);
                        stream.Close();
                    }
                }
            }
            IsStarted = false;
        }
    }

}
